#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include "head.h"
//修改小火车,附加哈希值
int put_server(int netfd, command_t *task, char *path) {
    char recvt[32 + sizeof(ssize_t)] = {0};
    int ret_recv = recv(netfd, recvt, sizeof(recvt), 0);
    ERROR_CHECK(ret_recv, -1, "error recv name");

	// WARNING: 文件名过长时候,小火车的文件名32上限需要修改

	char name[32] = {0};
    ssize_t lseek_offset = 0;
    // 写入数据
    memcpy(name, recvt, 32);
    memcpy(&lseek_offset, recvt + 32, sizeof(ssize_t));
    printf("写入的文件名是%s", name);

//=============================合并路径的======================================
    char *paths = "/home/luguanbo/123";
    char full_path[1024] = {0};
    // 将 paths, task->path连接,然后一写入full_path中
    snprintf(full_path, sizeof(full_path), "%s%s", paths, task->path);
    char full_path1[1024] = {0};
    snprintf(full_path1, sizeof(full_path), "%s%s", full_path, path);
//=============================================================================
    /*
    额外计算哈希值:FILE *popen(const char *command, const char *mode);
    popen函数用于创建一个进程，并与该进程进行通信。
	它的主要作用是执行一个命令并获取其标准输入或标准输出。
	FILE *pipe = popen("sha1sum file.txt", "r");
    -- FILE *pipe = popen("md5sum file.txt", "r");
	-->已经创建一个获取sha1sum值的管道,等待读取
	fread(buf,sizeof(char), sizeof(buf), pipe);
		-->每个元素大小为char,从pipe读取buf大小的数据到buf中
	printf("hash: \n%s", buf);
	系统调用sha1/md5计算哈希值并打印
	sha1sum --> 40 bit
	md5sum ---> 32 bit

	server端发送 文件名,文件长后,再附加两个哈希值sha1,md5:
	--> name | length | sha1 | md5
	*/

    printf("full_path1:%s\n", full_path1);	// 1024
    int filefd = open(full_path1, O_RDWR);	// -->已经获取到文件路径

	char sha[41] = {0};		// 两个都多一个位专用于存储 \0
	char md[33] = {0};		// -->用刚刚已经拿到的路径直接计算文件哈希值,并存储

	char filepath[1024] = {0};
	memcpy(filepath, "sha1sum ", 8);
	memcpy(filepath+8, full_path1, sizeof(full_path1)-8); 	// -->将命令组合起来,修正偏移量
	//此时,filepath应该是 --> "sha1sum full_path1"
	FILE *fp = popen(filepath, "r"); 						// -->计算哈希值,然后读取此处是sha1的
    fread(sha, sizeof(char), sizeof(sha)-1, fp);				//sha1哈希读取完毕
	sha[40] = 0;
	memset(filepath, 0, sizeof(filepath));					// 清空路径;
	pclose(fp);												// 关闭管道
	memcpy(filepath, "md5sum ", 7);
	memcpy(filepath + 7, full_path1, sizeof(full_path1) - 7);
	fp = popen(filepath, "r");
	fread(md, sizeof(char), sizeof(md)-1, fp);
	md[32] = 0;
	// 强制将第33位修改为\0
	printf("文件哈希值是\nsha1 = %s \nmd5 = %s \n", sha, md);
//==============================================================================

	ERROR_CHECK(filefd, -1, "error open file");
    struct stat file;
    fstat(filefd, &file);
    ssize_t length = file.st_size - lseek_offset;

    char *_info =
        (char *)calloc(sizeof(ssize_t) + sizeof(sha) + sizeof(md), sizeof(char));
    memcpy(_info, &length, sizeof(ssize_t));
    memcpy(_info + sizeof(ssize_t), sha, sizeof(sha));
    memcpy(_info + sizeof(ssize_t) + sizeof(sha), md, sizeof(md));
	// 获取文件长度,sha1/md5哈希值,然后发送这些信息

	send(netfd, _info, sizeof(_info), 0);

    // 文件信息发送完毕,开始发送文件本体
    printf("发送到文件大小是:%ld\n", length);

    ssize_t sent = 0;
    while (sent < length) {
        ssize_t ret_send = sendfile(netfd, filefd, &lseek_offset, length - sent);
        ERROR_CHECK(ret_send, -1, "error sendfile");
        sent += ret_send;
    }
    printf("文件发送完毕\n");
    close(filefd);
    return 0;
}
